﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Microsoft.Web.Media.SmoothStreaming;
using System.Collections.Generic;
using System.IO.IsolatedStorage;

namespace LiveStream.Caching
{
	//   [ExportAdaptiveCacheProvider]
	public class IsolatedStorageSmoothStreamingCache : ISmoothStreamingCache
	{
		const long CACHE_SIZE = 20000000000;

		static TimeSpan ONE_DAY = TimeSpan.FromDays(1);

		IsolatedStorageFile _isoFileArea;

		// Dictionary to track URL/filename pairs of data in cache.
		public Dictionary<string, string> _keyUrls = new Dictionary<string, string>(50);

		public IsolatedStorageSmoothStreamingCache()
		{
			_isoFileArea = IsolatedStorageFile.GetUserStoreForApplication();

			if (_isoFileArea.Quota < CACHE_SIZE)
				_isoFileArea.IncreaseQuotaTo(CACHE_SIZE);

			foreach (var filename in _isoFileArea.GetFileNames())
			{
				if (DateTime.Now - _isoFileArea.GetLastWriteTime(filename) > ONE_DAY)
				{
					_isoFileArea.DeleteFile(filename);
				}
			}

			List<string> keysToDelete = new List<string>();

			foreach (KeyValuePair<string, object> pair in IsolatedStorageSettings.ApplicationSettings)
			{
				if (_isoFileArea.FileExists((string)pair.Value))
				{
					if (!_keyUrls.ContainsValue((string)pair.Value))
						_keyUrls.Add(pair.Key, ((string)pair.Value));
				}
				else
				{
					keysToDelete.Add(pair.Key);
				}
			}

			foreach (var key in keysToDelete)
			{
				IsolatedStorageSettings.ApplicationSettings.Remove(key);
			}
		}

		public void ClearCache()
		{
			foreach (var filename in _isoFileArea.GetFileNames())
			{
				_isoFileArea.DeleteFile(filename);
			}
		}

		public IAsyncResult BeginRetrieve(CacheRequest request, AsyncCallback callback, object state)
		{
			CacheResponse response = null;
			CacheAsyncResult ar = new CacheAsyncResult();
			ar.strUrl = request.CanonicalUri.ToString();
			ar.Complete(response, true);
			return ar;
		}

		public CacheResponse EndRetrieve(IAsyncResult ar)
		{
			ar.AsyncWaitHandle.WaitOne();
			CacheAsyncResult cacheResult = ar as CacheAsyncResult;
			CacheResponse response = null;


			if (!cacheResult.strUrl.Contains("manifest"))
			{
				if (_keyUrls.ContainsKey(cacheResult.strUrl))
				{
					//IsolatedStorageFile isoFileArea = IsolatedStorageFile.GetUserStoreForApplication();
					string filename = _keyUrls[cacheResult.strUrl];

					if (!string.IsNullOrEmpty(filename) && _isoFileArea.FileExists(filename))
					{
						IsolatedStorageFileStream stream =
							_isoFileArea.OpenFile(filename, System.IO.FileMode.Open, System.IO.FileAccess.Read);
						response = new CacheResponse(stream);
					}
				}
			}
			else
			{
				var junk = false;
			}

			if (response != null)
				return response;
			else
				return response = new CacheResponse(0, null, null, null,
					System.Net.HttpStatusCode.NotFound, "Not Found", DateTime.Now);
		}

		public IAsyncResult BeginPersist(CacheRequest request, CacheResponse response, AsyncCallback callback, object state)
		{
			state = false;
			CacheAsyncResult ar = new CacheAsyncResult();

			if (!_keyUrls.ContainsKey(request.CanonicalUri.ToString()))
			{
				//state = true;
				ar.strUrl = request.CanonicalUri.ToString();
				ar.Complete(response, true);
				return ar;
			}

			ar.Complete(null, true);
			return ar;
		}

		public bool EndPersist(IAsyncResult ar)
		{
			ar.AsyncWaitHandle.WaitOne();
			CacheAsyncResult cacheResult = ar as CacheAsyncResult;

			if (cacheResult.Result != null && !cacheResult.strUrl.Contains("manifest"))
			{
				//				IsolatedStorageFile isoFileArea = IsolatedStorageFile.GetUserStoreForApplication();
				CacheResponse cacheResponse = cacheResult.Result as CacheResponse;

				if (cacheResponse.Response.Length < _isoFileArea.AvailableFreeSpace)
				{
					string fileGuid = Guid.NewGuid().ToString();

					if (!_keyUrls.ContainsValue(fileGuid) && !_keyUrls.ContainsKey(cacheResult.strUrl))
					{

						IsolatedStorageFileStream isoFile = _isoFileArea.CreateFile(fileGuid);

						cacheResponse.WriteTo(isoFile);
						isoFile.Close();

						_keyUrls.Add(cacheResult.strUrl, fileGuid);
						// Save key/value pairs for playback after application restarts.
						IsolatedStorageSettings.ApplicationSettings.Add(cacheResult.strUrl, fileGuid);
						IsolatedStorageSettings.ApplicationSettings.Save();

						return true;
					}
				}
			}
			return false;
		}
	}
}
